package com.xidata.dict.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xidata.dict.entity.CodeDict;
import com.xidata.dict.model.CodeLookupNotFoundStrategy;
import com.xidata.dict.model.CodeTranslateRequest;
import com.xidata.dict.model.LookupRequest;
import com.xidata.dict.model.TranslateResponse;
import com.xidata.dict.service.CodeDictService;
import com.xidata.dict.service.CodeMainLanguageService;
import com.xidata.dict.service.CodeTranslateService;
import com.xidata.dict.service.TranslateService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Optional;
import java.util.UUID;

@Service
@Slf4j
public class CodeTranslateServiceImpl implements CodeTranslateService, InitializingBean {
    @Resource
    CodeDictService codeDictService;

    @Resource
    CodeMainLanguageService codeMainLanguageService;

    @Resource
    TranslateService translateService;

    @Override
    public TranslateResponse translate(CodeTranslateRequest request, JSON data) {

        if (data instanceof JSONArray) {
            translateArray(request, (JSONArray) data);
        } else {
            translateObject(request, (JSONObject) data);
        }

        TranslateResponse response = new TranslateResponse();
        response.setTraceId(getTraceId());
        response.setData(data);
        return response;
    }

    private void translateObject(CodeTranslateRequest request, JSONObject data) {

        boolean dictFound = translateCode(request, data);

        String childrenProperty = request.getChildrenProperty();
        if (StringUtils.isNotEmpty(childrenProperty) && data.containsKey(childrenProperty)) {
            JSONArray jsonArray = data.getJSONArray(childrenProperty);
            if (jsonArray != null && !jsonArray.isEmpty()) {
                translateArray(request, jsonArray);
            }
        }


    }

    private void translateArray(CodeTranslateRequest request, JSONArray data) {
        data.forEach(object -> {
            translateObject(request, (JSONObject) object);
        });
    }

    private boolean translateCode(CodeTranslateRequest request, JSONObject data) {
        String codeProperty = request.getCodeProperty();
        if (!data.containsKey(codeProperty)) {
            return false;
        }
        String code = data.getString(codeProperty);

        String targetLanguage = request.getTargetLanguage();
        Optional<CodeDict> dictOptional = codeDictService.lookup(request.getCodeType(), code, targetLanguage);
        if (dictOptional.isPresent()) {
            String text = dictOptional.get().getText();
            data.put(request.getValueProperty(), text);
            return true;
        }

        if (request.getStrategy() == CodeLookupNotFoundStrategy.ONLINE_TRANSLATE) {

            LookupRequest lookupRequest = new LookupRequest();
            lookupRequest.setSourceLanguage(codeMainLanguageService.getMainLanguage());
            String codeText = codeMainLanguageService.getCodeText(request.getCodeType(), code);

            if (StringUtils.isEmpty(codeText)) return false;

            lookupRequest.setText(codeText);
            lookupRequest.setTargetLanguage(targetLanguage);

            String translate = translateService.translate(lookupRequest);


            if (!translated(translate, codeText)) {
                return false;
            }
            data.put(request.getValueProperty(), translate);
            codeDictService.add(request.getCodeType(), code, targetLanguage, translate);
            return true;

        }

        return false;
    }

    private boolean translated(String lookup, String value) {
        return StringUtils.isNotEmpty(lookup) && !lookup.equals(value);
    }

    @NotNull
    private String getTraceId() {
        return UUID.randomUUID().toString();
    }

    @Override
    public void afterPropertiesSet() throws Exception {
    }
}
